﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Coslen.Framework.Attributes;
using Coslen.TahorCRM.Domain.Entities.Custom;
using Coslen.TahorCRM.Domain.Entities.ViewModels.Editing;
using Coslen.TahorCRM.Domain.Entities.ViewModels.Searching;
using Coslen.TahorCRM.Domain.Services.Interfaces;
using Coslen.TahorCRM.Security;
using Coslen.TahorCRM.UI.www.Controllers;
using Ninject;

namespace Coslen.TahorCRM.UI.www.Areas.Events.Controllers
{
    public class EventController : TahorBaseController
    {
        [Inject]
        public IEventService EventService { get; set; }

        //
        // GET: /Event/
        [Authorize(Roles = "CanViewEvents")]
        //public ActionResult Index(EventSearchViewModel model)
        public ActionResult Index(string Period, int? page, int? PageSize)
        {
            // Set up our default values
            string defaultPeriod = Session["Period"] == null ? "This Month" : Session["Period"].ToString();
            
            // Determine if the parameters have values
            Period = string.IsNullOrWhiteSpace(Period) ? defaultPeriod : Period;
            
            EventSearchViewModel model = new EventSearchViewModel();
            model.Period = Period;
            model.PageNumber = page;
            model.PageSize = PageSize;

            try
            {
                if (model == null)
                {
                    model = new EventSearchViewModel();
                    // any defaults???
                }

                model = EventService.GetEventSearchViewModel(model);

                // Put this into the ViewModel so our Pager can get at these values
                ViewBag.Period = model.Period;
                ViewBag.PageSize = model.PageSize;

                // Put the info into the Session so that when we browse away from the page and come back that the last settings are rememberd and used.
                Session["Period"] = model.Period;

                return View(model);
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            throw new ApplicationException("Should  not be able to get here!");
        }

        //
        // GET: /Event/Notice/5
        //[Authorize(Roles = "CanViewEvents")]
        [AllowAnonymous]
        public ActionResult Notice(int id)
        {
            try
            {
                EventEditViewModel model = EventService.GetEventEditViewModelById(id);
                return View(model);
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            throw new ApplicationException("Should  not be able to get here!");
        }

        //
        // GET: /Event/Details/5
        [Authorize(Roles = "CanViewEvents")]
        public ActionResult Details(int id)
        {
            try
            {
                EventEditViewModel model = EventService.GetEventEditViewModelById(id);
                return View(model);
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            throw new ApplicationException("Should  not be able to get here!");
        }

        //
        // GET: /Event/Create
        [Authorize(Roles="CanEditEvents")]
        public ActionResult Create(string source = "")
        {
            try
            {
                EventEditViewModel model = EventService.GetNewEventEditViewModel();
                model.source = source;
                model.sourceUrl = ConvertSourceToSourceUrl(source, 0);
                model.Event.CreatedByUserId = ((TahorPrincipal)HttpContext.User).User.UserId;

                return View(model);
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            throw new ApplicationException("Should  not be able to get here!");
        }

        //
        // POST: /Event/Create
        [HttpPost]
        [Authorize(Roles = "CanEditEvents")]
        public ActionResult Create(EventEditViewModel model)
        {
            try
            {
                // TODO: Add insert logic here
                if (ModelState.IsValid)
                {
                    EventService.SaveEvent(model.Event);
                    if (!string.IsNullOrEmpty(model.source))
                    {
                        return RedirectToSource(model.source, model.Event.EventId);
                    }
                    else
                    {
                        return RedirectToAction("Index");
                    }
                }
                else
                {
                    ProcessModelState(ModelState);
                }
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            // Repopulate the Event Type Lists
            EventEditViewModel tmpModel = EventService.GetNewEventEditViewModel();
            model.EventTypeList = tmpModel.EventTypeList;

            return View(model);
        }

        //
        // GET: /Event/Edit/5
        [Authorize(Roles = "CanEditEvents")]
        public ActionResult Edit(int id, string source = "")
        {
            try
            {
                EventEditViewModel model = EventService.GetEventEditViewModelById(id);
                model.source = source;
                model.sourceUrl = ConvertSourceToSourceUrl(source, id);

                return View(model);
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            throw new ApplicationException("Should  not be able to get here!");
        }

        //
        // POST: /Event/Edit/5
        [HttpPost]
        [Authorize(Roles = "CanEditEvents")]
        public ActionResult Edit(EventEditViewModel model)
        {
            try
            {
                // TODO: Add update logic here
                if (ModelState.IsValid)
                {
                    EventService.SaveEvent(model.Event);

                    if (!string.IsNullOrEmpty(model.source))
                    {
                        return RedirectToSource(model.source, model.Event.EventId);
                    }
                    else
                    {
                        return RedirectToAction("Index");
                    }
                }
                else
                {
                    ProcessModelState(ModelState);
                }

                return RedirectToAction("Index");
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            // TODO: add any alter failed edit model logic here....
            // Repopulate the Event Type Lists
            EventEditViewModel tmpModel = EventService.GetNewEventEditViewModel();
            model.EventTypeList = tmpModel.EventTypeList;

            return View(model);
        }

        //
        // GET: /Event/Delete/5
        [Authorize(Roles = "CanEditEvents")]
        public ActionResult Delete(int id, string source = "")
        {
            try
            {
                EventEditViewModel model = EventService.GetEventEditViewModelById(id);
                model.source = source;
                model.sourceUrl = ConvertSourceToSourceUrl(source, 0);

                return View(model);
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            throw new ApplicationException("Should  not be able to get here!");
        }

        //
        // POST: /Event/Delete/5
        [HttpPost, ActionName("Delete")]
        [Authorize(Roles = "CanEditEvents")]
        public ActionResult DeleteConfirm(int id)
        {
            try
            {
                // TODO: Add delete logic here
                EventEditViewModel model = EventService.GetEventEditViewModelById(id);
                EventService.DeleteEvent(model.Event);

                if (!string.IsNullOrEmpty(model.source))
                {
                    return RedirectToSource(model.source, 0);
                }
                else
                {
                    return RedirectToAction("Index");
                }
            }
            catch (DbEntityValidationException dbEx)
            {
                ProcessDbEntityValidationException(dbEx);
            }
            catch (DbUpdateException dbEx)
            {
                ProcessDbUpdateException(dbEx);
            }
            catch (SqlException sqlEx)
            {
                ProcessSqlException(sqlEx);
            }

            return RedirectToAction("Delete", new { id = id });
        }


        //public JsonResult GetMonthsEvents(int month, int year, int userId = 0)
        public JsonResult GetMonthsEvents(double start, double end, int userId)
        {
            var fromDate = ConvertFromUnixTimestamp(start);
            var toDate = ConvertFromUnixTimestamp(end);
            
            //int userId = 0;

            List<JSonCalendarEvent> events = EventService.GetEventsForMonthAndUser(fromDate, toDate, userId);

            return Json(events.ToArray(), JsonRequestBehavior.AllowGet); 
        }

        private DateTime ConvertFromUnixTimestamp(double timestamp)
        {

            var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);

            return origin.AddSeconds(timestamp);

        }

        [AllowAnonymous]
        public ActionResult PrintCalendar()
        {
            return View();
        }
    }
}
